1. Field of the Invention
The invention relates to software development. Specifically, the invention relates to apparatus, systems, and methods for identifying fixed memory address errors in source code at build time.
2. Description of the Related Art
Software development generally includes writing source code (human readable code) and then using various tools to convert the source code into machine code also referred to as executable code, machine-readable code, executable code image, image file or the like. In general purpose software development, the programmer is not concerned with where specific portions of the source code, such as particular routines and data structures, are placed in memory when the object code is executed. Typically, these components are dynamically loaded and could be relocated in memory by the operating system as needed.
However, embedded system software programmers are typically very concerned with how components in source code are eventually organized in memory of the embedded system particularly where the executable code is loaded once statically and executable code structures are not relocated by an operating system of the embedded system. Generally, the use and organization of memory of the embedded system is carefully coordinated between one or more programmers and/or teams of programmers. This coordination is often required in order to use a particular data structure at a particular memory address (referred to herein as a hardcoded memory address) for messaging between one or more sub-systems of the embedded system.
Typically, the memory in an embedded system is shared by multiple hardware devices including Central Processing Unit (CPUs), Application Specific Integrated Circuits (ASICs), and the like. These hardware devices may be hardwired to branch to a specific location in the shared memory (known as an entry point) to begin executing executable code, also referred to as microcode. Accordingly, as the microcode originates in source code files, hardcoded memory addresses in the source code are used to place the microcode where the hardware devices are expecting to find it.
Certain embedded systems may include different types of memory that are more suitable for particular needs of operations in the embedded system. For example, the embedded system can include Read-Only-Memory (ROM), Random-Access-Memory (RAM), Cached memory, on-board high speed memory, external memory, and the like. The different types of memory are often logically combined into a single memory block with each type of memory having a specific start and stop address. Accordingly, programmers can use the hardcoded start and stop addresses to programmatically manage where certain data structures are stored in the memory hardware. Hardcoded memory addresses are often used to optimize performance and reliability of embedded systems.
Hardcoded memory addresses are generally designated using hexadecimal notation. Generally, a memory map or memory layout is used to coordinate and organize use of memory resources in an embedded system. The memory map designates where executable code will be stored as well as data structures, both initialized and uninitialized.
Unfortunately, conventional programming languages and tools in widespread use fail to provide a common location for designating hardcoded addresses. Furthermore, tracking sizes and locations of hardcoded memory structures, even when using a memory map, can be difficult because programmers may underestimate the size required for data structures having a variable size. Managing hardcoded memory addresses can be further complicated by a lack of communication between programmers due to different software development schedules and affiliations of the programmers with different companies all collaborating to produce the embedded system.
These challenges often lead to errors in use of the memory. Certain data structures may corrupt others because an incorrect start or stop address is specified. This type of memory error is referred to herein as a memory boundary error or an overlap error. Other custom-defined memory regions can be filled with data structures for which the combined size is greater than the custom-defined memory region. This type of memory error is referred to herein as a memory capacity error or an overflow error.
Unfortunately, conventional programming tools do not permit detection of these errors until the source code is fully compiled and built in to executable code and the executable code is executed. Generally, embedded system programmers are forced to wait for these errors to be discovered in a test environment or worse yet in the deployed environment.
Management of hardcoded memory addresses is made more difficult because conventional embedded system programming tools require that separate definition files be used in the build process to designate hardcoded memory addresses in the source code for the compiler and in a link directive file for the linker. FIG. 1 illustrates a conventional build process that requires separate definition files to define hardcoded memory addresses both for data structures and for memory regions.
The system 100 includes a compiler 102 and a linker 104. Optionally, an assembler may assemble assembly code produced by the compiler 102 and provide the assembled code to the linker 104. Alternatively, the assembler can be integrated with the compiler 102.
The compiler 102 reads in one or more source code files 106 and produces object code. Generally, the source code 106 references variable constants that have associated hardcoded memory addresses. A programmer defines the hardcoded memory addresses directly in source code. The hardcoded memory addresses or constants associated therewith are used in logic of the source code.
The linker 104 links multiple object code files into a single executable image or file. The linker 104 is configured to produce an image file 108 compatible with the memory architecture of the target embedded system platform. In order to define custom memory regions for certain data structures and to utilize specialized memory hardware, the linker reads a link directive file or script 110. The link directive file 110 includes hardcoded memory addresses and commands in a syntax understandable to the linker 104.
Unfortunately, the same memory addresses are designated in both the source code 106 and the link directive file 110. Consequently, changes to one file 106 must be duplicated in the other file 110 and vice versa. Programmers may fail to make the change in both places. Similarly in large projects, the ripple effect of a change in one file may be untraceable through the other file or files.
FIG. 1 also illustrates various errors that incorrect hardcoded memory addresses can cause. For example, processors 112, 114 may branch to entry points 116, 118 but the microcode for that processor 112, 114 may not be positioned at the expected entry point 116, 118. A data structure such as data structure B2 may begin prior to the stop address of data structure B1 (boundary error). Another data structure 120 of a fixed size may attempt to include data structures DS1, DS2, and DS3 that exceed the capacity of the data structure 120. This can happen as fields within the data structures combine to take more space than was anticipated by the programmer.
From the foregoing discussion, it should be apparent that a need exists for an apparatus, system, and method for identifying fixed memory address errors in source code at build time. Such an apparatus, system, and method would allow consolidation of hardcoded memory address definitions. In addition, the apparatus, system, and method would check hardcoded memory address definition during build time such that hardcoded memory address are detectable before the executable code is executed.